package model;

import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.ResourceBundle;

import controller.Controller;

import util.reflection.Reflection;

import model.semantics.ConstNode;
import model.semantics.Node;
import model.turtle.Turtle;
import model.turtle.Position;

public class TurtleState extends State<Integer> {

    private List<Turtle> myTurtles;
    private Position initialPos;
    private Map<String, String> supportedCommands;
    private static final String resource = "resources.commandMapping";

    public TurtleState() {
        super(0);
        supportedCommands = new HashMap<String, String>();
        ResourceBundle myResources = ResourceBundle.getBundle(resource);
        for (String key : myResources.keySet()) {
            supportedCommands.put(key, myResources.getString(key));
        }

        initialPos = new Position(0, 0, 0);
        myTurtles = new LinkedList<Turtle>();
        Turtle tmp = new Turtle(initialPos);
        tmp.setActive(true);
        myTurtles.add(tmp);
    }

    public TurtleState clone() {
        return new TurtleState();
    }

    public List<Turtle> getTurtles() {
        List<Turtle> rtn = new LinkedList<Turtle>();
        for (Turtle tmp : myTurtles) {
            if (tmp.getActive())
                rtn.add(tmp);
        }
        return rtn;
    }

    public List<Integer> getActiveTurtles() {
        List<Integer> rtn = new LinkedList<Integer>();
        for (int i = 0; i < myTurtles.size(); i++) {
            if (myTurtles.get(i).getActive())
                rtn.add(i);
        }
        return rtn;
    }

    public void setTurtles(List<Integer> turtles) {
        for (Turtle tmp : myTurtles) {
            tmp.setActive(false);
        }
        for (Integer index : turtles) {
            int size = myTurtles.size();
            if (size >= (index + 1)) {
                myTurtles.get(index).setActive(true);
            } else {
                for (int i = 0; i < (index + 1 - size); i++) {
                    myTurtles.add(new Turtle(initialPos));
                }
                myTurtles.get(index).setActive(true);
            }
        }
    }

    @Override
    public Node<Integer> getDefaultValue() {
        return new ConstNode<Integer>(0);
    }

    public List<Turtle> getTurtleList() {
        return myTurtles;
    }

    public Integer runCommand(Object... values) {
        boolean flag = true;
        int rtn = 0;

        // clear screen is different from other commands
        if (((String) values[0]).equals("clearscreen")
                || ((String) values[0]).equals("cs")) {
            for (Turtle tmp : myTurtles) {
                if (flag) {
                    rtn = tmp.clearScreen();
                    flag = false;
                } else
                    tmp.clearScreen();
            }
            return rtn;
        }

        if (values.length == 1) {
            for (Turtle tmp : getTurtles()) {
                if (flag) {
                    rtn = (Integer) Reflection.callMethod(tmp,
                            supportedCommands.get((String) values[0]));
                    flag = false;
                } else
                    Reflection.callMethod(tmp,
                            supportedCommands.get((String) values[0]));
            }
            return rtn;
        }

        Object[] argList = new Object[values.length - 1];
        System.arraycopy(values, 1, argList, 0, argList.length);
        for (Turtle tmp : getTurtles()) {
            if (flag) {
                rtn = (Integer) Reflection.callMethod(tmp,
                        supportedCommands.get((String) values[0]), argList);
                flag = false;
            } else
                Reflection.callMethod(tmp,
                        supportedCommands.get((String) values[0]), argList);
        }
        return rtn;
    }
}
